﻿
Imports osi.root.connector
Imports osi.root.delegates
Imports osi.root.formation
Imports osi.root.procedure
Imports osi.root.utils
Imports osi.service.argument

Public Class block_wrapper
    Implements block

    Public ReadOnly inner As block
    Public ReadOnly wrapped As block

    Private Sub New(ByVal inner As block, ByVal wrapped As block)
        assert(Not inner Is Nothing)
        assert(Not wrapped Is Nothing)
        Me.inner = inner
        Me.wrapped = wrapped
    End Sub

    Public Shared Function bind_wrap(ByVal v As var, ByRef o As _do_val_ref(Of block, block, Boolean)) As Boolean
        Dim f As _do_val_ref(Of block, block, Boolean) = Nothing
        If device_wrapper.bind(v, f) AndAlso
           assert(Not f Is Nothing) Then
            o = Function(i As block, ByRef r As block) As Boolean
                    Dim wrapped As block = Nothing
                    If f(i, wrapped) Then
                        r = New block_wrapper(i, wrapped)
                        Return True
                    Else
                        Return False
                    End If
                End Function
            Return True
        Else
            Return False
        End If
    End Function

    Public Shared Function bind_wrap(ByVal v As var,
                                     ByRef o As Func(Of block, pointer(Of block), event_comb)) As Boolean
        Dim f As Func(Of block, pointer(Of block), event_comb) = Nothing
        If device_wrapper.bind(v, f) AndAlso
           assert(Not f Is Nothing) Then
            o = Function(i As block, r As pointer(Of block)) As event_comb
                    Dim ec As event_comb = Nothing
                    Dim wrapped As pointer(Of block) = Nothing
                    Return New event_comb(Function() As Boolean
                                              wrapped = New pointer(Of block)()
                                              ec = f(i, wrapped)
                                              Return waitfor(ec) AndAlso
                                                     goto_next()
                                          End Function,
                                          Function() As Boolean
                                              Return ec.end_result() AndAlso
                                                     eva(r, New block_wrapper(i, +wrapped)) AndAlso
                                                     goto_end()
                                          End Function)
                End Function
            Return True
        Else
            Return False
        End If
    End Function

    Public Shared Function unwrap(ByVal i As block, ByRef o As block) As Boolean
        Dim w As block_wrapper = Nothing
        If cast(Of block_wrapper)(i, w) AndAlso
           assert(Not w Is Nothing) AndAlso
           assert(Not w.inner Is Nothing) Then
            o = w.inner
            Return True
        Else
            Return False
        End If
    End Function

    Public Shared Function create(ByVal v As var,
                                  ByVal inner As block,
                                  ByVal o As pointer(Of block)) As event_comb
        Dim ec As event_comb = Nothing
        Dim wrapped As pointer(Of block) = Nothing
        Return New event_comb(Function() As Boolean
                                  wrapped = New pointer(Of block)()
                                  ec = device_wrapper.wrap(v, inner, wrapped)
                                  Return waitfor(ec) AndAlso
                                         goto_next()
                              End Function,
                              Function() As Boolean
                                  Return ec.end_result() AndAlso
                                         eva(o, New block_wrapper(inner, +wrapped)) AndAlso
                                         goto_end()
                              End Function)
    End Function

    Public Shared Function create(ByVal v As var,
                                  ByVal inner As block,
                                  ByRef o As block) As Boolean
        Dim r As block = Nothing
        If device_wrapper.wrap(v, inner, r) Then
            o = New block_wrapper(inner, r)
            Return True
        Else
            Return False
        End If
    End Function

    Public Function send(ByVal buff() As Byte,
                         ByVal offset As UInt32,
                         ByVal count As UInt32) As event_comb Implements block_injector.send
        Return wrapped.send(buff, offset, count)
    End Function

    Public Function receive(ByVal result As pointer(Of Byte())) As event_comb Implements block_pump.receive
        Return wrapped.receive(result)
    End Function

    Public Function sense(ByVal pending As pointer(Of Boolean),
                          ByVal timeout_ms As Int64) As event_comb Implements sensor.sense
        Return wrapped.sense(pending, timeout_ms)
    End Function
End Class
